﻿using System;
using System.Collections.Generic;
using System.Linq;

using Bootstrap5.Abstractions;

using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Rendering;

namespace Bootstrap5;

[CssClass("toast-container")]
public class ToastContainer:BootstrapComponentBase, IDisposable
{
    public ToastContainer()
    {
    }
    /// <summary>
    /// Gets or sets the toast service.
    /// </summary>
    [Inject] IToastService ToastService { get; set; }
    /// <summary>
    /// Gets or sets the navigation manager.
    /// </summary>
    [Inject] NavigationManager NavigationManager { get; set; }

    [Parameter] public ToastPlacement Placement { get; set; } = ToastPlacement.TopRight;

    /// <summary>
    /// Gets or sets a value indicating whether to clear all toast messages when location changed.
    /// </summary>
    [Parameter] public bool ClearWhenLocationChanged { get; set; }

    /// <summary>
    /// Gets or sets the time of seconds to show message.
    /// </summary>
    [Parameter] public int? Interval { get; set; } = 5;

    /// <summary>
    /// Gets or sets the fade interval.
    /// </summary>
    [Parameter] public int FadeInterval { get; set; } = 30;

    /// <summary>
    /// Gets or sets the key.
    /// </summary>
    [Parameter] public string Key { get; set; } = "Default";

    /// <summary>
    /// Gets or sets the toast list.
    /// </summary>
    internal List<ToastInstance> Toasts { get; set; } = new List<ToastInstance>();

	protected override void OnInitialized()
	{
            ToastService.OnShow += Show;

            if (ClearWhenLocationChanged)
            {
                NavigationManager.LocationChanged += Navigationmanager_LocationChanged;
            }
	}

	protected override void CreateCssClass(ICssClassBuilder builder)
    {
        builder
            .Add("position-fixed")
            .Add("p-3").Add(Placement.GetEnumCssClass());
    }

    protected override void BuildRenderTree(RenderTreeBuilder builder)
    {
        builder.OpenElement(0, "div");
        BuildCommonAttributes(builder);
        builder.AddAttribute(9, "style", "z-index:9999");
        builder.AddContent(10, content =>
        {
            this.CreateCascadingValueComponent<ToastContainer>(content, BuildToasts, isFixed: true);
        });
        builder.CloseElement();
    }

    void BuildToasts(RenderTreeBuilder builder)
	{
        var i = 0;
        foreach (var item in Toasts.OrderBy(m => m.Timestamp))
		{
            builder.OpenComponent<ToastBox>(0);
            builder.SetKey(item);
            builder.AddAttribute(1, nameof(ToastBox.Id), item.Id);
            builder.AddAttribute(2, nameof(ToastBox.FadeInterval), FadeInterval);
            builder.AddAttribute(3, nameof(ToastBox.Options), item.Options);
            builder.AddAttribute(4, nameof(ToastBox.Interval), Interval);
            builder.CloseComponent();
            i++;
		}
	}

    /// <summary>
    /// Removes the specified toast identifier.
    /// </summary>
    /// <param name="toastId">The toast identifier.</param>
    public void Remove(Guid toastId)
    {
        InvokeAsync(() =>
        {
            Toasts.Remove(Toasts.SingleOrDefault(m => m.Id == toastId));
            StateHasChanged();
        });
    }
    /// <summary>
    /// Clear all toast messages.
    /// </summary>
    public void Clear()
    {
        InvokeAsync(() =>
        {
            Toasts.Clear();
            StateHasChanged();
        });
    }
    /// <summary>
    /// Cleanup references to this control
    /// </summary>
    public void Dispose()
    {
        ToastService.OnShow -= Show;
        NavigationManager.LocationChanged -= Navigationmanager_LocationChanged;
    }

    private void Navigationmanager_LocationChanged(object sender, EventArgs e)
        => Clear();



    /// <summary>
    /// Show the toast with specified setting.
    /// </summary>
    /// <param name="options">The setting of toast message.</param>
    public void Show(ToastOptions options)
    {
        InvokeAsync(() =>
        {   
            if (options.Key == Key)
            {
                Toasts.Add(new ToastInstance
                {
                    Id = Guid.NewGuid(),
                    Options = options,
                    Timestamp = DateTime.Now
                });
                StateHasChanged();
            }
        });
    }
}
